package com.asa.hutils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;



import com.asa.fushu.bean.Fushu;
import com.asa.hutils.teizheng.Eigenvalue;
import com.asa.hutils.teizheng.structure.Matrix;
import com.asa.utils.Calculate;
import com.asa.utils.MathUtils;

/**
 * 这里面求矩阵的的逆呀，特征值呀，特征向量呀，阶数高了感觉会比较慢
 * 
 * @author Administrator
 * 
 */
public class MathHUtils {

	public static final double jingdu=0.0001;

	public static final double to0=0.000001;

	
	
	/**
	 * 求解矩阵的逆
	 * 
	 * @param a
	 * @return
	 * @throws Exception
	 */
	public static double[][] juzhengni(double[][] a) throws Exception {
		//System.out.println("=============================");
		double[][] b = new double[a.length][a.length * 2];

		for (int i = 0; i < b.length; i++) {
			for (int j = 0; j < b.length; j++) {
				
				if (a[i][j]==0) {
					b[i][j] = 0.00001;

				}else {
					b[i][j] = a[i][j];

				}
			}
		}
		for (int i = 0; i < b.length; i++) {
			for (int j = b.length; j < b.length * 2; j++) {
				// //System.out.println(i+" "+j);
				if ((j - b.length) == i) {
					b[i][j] = 1;
				} else {
					b[i][j] = 0;
				}

			}
		}

//		for (int i = 0; i < b.length; i++) {
//			for (int j = 0; j < b[i].length; j++) {
//				System.out.print(b[i][j] + "  ");
//			}
//			//System.out.println();
//		}

		double[][] ni = Ni.getNi(b);
		if (ni == null) {
			throw new Exception("该矩阵不可逆");
		}
		double[][] c = new double[a.length][a.length];
//		//System.out.println("nininininininininininininininininini");
//		for (int i = 0; i < ni.length; i++) {
//			for (int j = 0; j < ni[i].length; j++) {
//				System.out.print(ni[i][j] + "    ");
//			}
//			//System.out.println();
//		}
//		//System.out.println("nininininininininininininininininini");
		for (int i = 0; i < c.length; i++) {
			for (int j = 0; j < c.length; j++) {
				c[i][j] = ni[i][j + c.length];
			}
		}

		return c;
	}

	/**
	 * 求解矩阵的特征值
	 * 这东西其实也是瓜皮，如果解是虚数，它会卡住
	 * 这是因为它使用的是迭代法，找不出值就会一直迭代下去
	 * @param a
	 * @return
	 */
	public static double[] juzhengtezhengzhi(double[][] a) {
		//这个求特征值的方法我是我写的，不知道怎么改，它的那个对于0的判断有问题，这样赋个极小值可以凑合着解决一下
		a = copy(a);
		
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < a[i].length; j++) {
				if (a[i][j]==0) {
					a[i][j] = 0.000001;
				}
			}
		}
		
		
		double[] data = new double[a.length * a.length];
		int n = 0;
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < a[i].length; j++) {
				data[n] = a[i][j];
				n++;
			}
		}
		Matrix mat = new Matrix(a.length, a.length, data);
		Matrix eigenvalues = Eigenvalue.getEigenvalues(mat);
		// eigenvalues.print();
		double[] getall = eigenvalues.getall();
		
		Arrays.sort(getall);
		
		return getall;
	}

	
	
	public static double[][] juzhengtezhengxiangliang(double[][] a) throws Exception {
		
		double[] r = juzhengtezhengzhi(a);

		return juzhengtezhengxiangliang(a, r);
		
		
	}

	
	
	/**
	 * 	求矩阵的特征向量
	 * 	这里处理了重根的情况
	 * 	重根的特征向量，并不能把矩阵转化成约旦标准型，依然是把它转化成对角线状态
	 * @param a
	 *            要求特征向量的矩阵
	 * @return 返回特征向量
	 * @throws Exception
	 */
	public static double[][] juzhengtezhengxiangliang(double[][] a,double[] r) throws Exception {

//		Arrays.sort(r);
		
		double[][] base = new double[a.length][a.length];
		double[][] asb = new double[a.length][a.length]; // 存储向量解数据
		double[] b = new double[a.length - 1];
		
		
		//考虑到r（特征值）可能存在重复的情况
		//处理重根的
		Map<Integer,Integer> ischong_index = new HashMap<Integer,Integer>();//记录重根位置
		Map<Double,Integer> count = new HashMap<Double, Integer>();
		for (int i = 0; i < r.length; i++) {
			Double d = r[i];
					
			if (count.containsKey(d)) {
				Integer ci = count.get(d);
				ci++;
				ischong_index.put(i, ci);
				count.put(d, ci);
			}else {
				count.put(d, 0);
			}
					
		}
		
		
		
		
		
		
		
		
		
		
		//System.out.println("特征值为：");
//		for (int i = 0; i < r.length; i++) {
//			//System.out.println(r[i]);
//		}
		//System.out.println("========原始数据==========");
//		for (int i = 0; i < a.length; i++) {
//			for (int j = 0; j < a.length; j++) {
//				System.out.print(a[i][j] + "      ");
//			}
//			//System.out.println();
//		}
//		for (int i = 0; i < r.length; i++) {
//			//System.out.println(r[i]);
//		}
		//System.out.println("==================");
		for (int i = 0; i < r.length; i++) {
//			for (int j = 0; j < base.length; j++) {
//				for (int k = 0; k < base.length; k++) {
//					base[j][k] = a[j][k];
//				}
//			}
			base = copy(a);

			Integer chong = ischong_index.get(i);
			if (chong!=null&&chong>0) {
				
				double r_1 = r[i-1];
				double[] ds = asb[i-1];
				double[][] p_1 = {ds};
				
				

				double[][] I = MathHUtils.getI(base.length);
				double[][] chenfa2 = chenfa(I, -r_1);
				
				double[][] jiafa = MathHUtils.jiafa(base, chenfa2);
				
				double[][] juzhengni = MathHUtils.juzhengni(jiafa);
				double[][] zhuanzhi = MathHUtils.zhuanzhi(juzhengni);
				
				double[][] chenfa = MathHUtils.chenfa(p_1, zhuanzhi);
				
				asb[i] = chenfa[0];
				
				continue;
			}
			
			
			
			
			
			
			
			
			//System.out.println("========基础base==========");
//			for (int k = 0; k < base.length; k++) {
//				for (int j = 0; j < base.length; j++) {
//					System.out.print(base[k][j] + "     ");
//				}
//				//System.out.println();
//			}
			for (int j = 0; j < r.length; j++) {
				System.out.println(base[j][j] +"  ...  "+ r[i]);
				base[j][j] = base[j][j] - r[i];
				
			}
			System.out.println("=============第" + i + "次============");
			for (int k = 0; k < base.length; k++) {
				for (int j = 0; j < base.length; j++) {
					System.out.print(base[k][j] + "  这个是base   ");
				}
				System.out.println();
			}
			System.out.println();
			
			
			
			
			if (base.length==2) {
				System.out.println("base.length==2进来了吗");
				double[] bb = {0,0};
				double[] result=erweifangchengzu_tongjie(base,bb);
				
				System.out.println("结果："+result[0]+"    "+result[1]);
				asb[i] = result;

				
				continue;

			}
			
			
			
			
			
			double[][] c = new double[a.length - 1][a.length - 1];

			int choosejuzhenglei = choosejuzhenglei(base);
			int rejectjuzhenghang = rejectjuzhenghang(base);
			
			
//			System.out.println("......................" + choosejuzhenghang);
			for (int k = 0; k < b.length; k++) {
//				System.out.println("万恶之源"+(-base[k + choosejuzhenghang][0]));
				if (rejectjuzhenghang==k) {
					continue;
				}
				
				b[k] = -base[k][choosejuzhenglei];
			}
			if (rejectjuzhenghang!=b.length) {
				for (int j = 0; j < c.length; j++) {
					b[b.length-1] = -base[base.length-1][choosejuzhenglei];
				}
			}
			
			
			
			for (int k = 0; k < c.length; k++) {
				if (rejectjuzhenghang==k) {
					continue;
				}
				for (int j = 0; j < c.length; j++) {
					if (choosejuzhenglei<=j) {
						c[k][j] = base[k][j + 1];

					}else {
						c[k][j] = base[k][j];
					}
					
				}
			}
			
			if (rejectjuzhenghang!=c.length) {
				for (int j = 0; j < c.length; j++) {
					if (choosejuzhenglei<=j) {
						c[c.length-1][j] = base[base.length-1][j + 1];
					}else {
						c[c.length-1][j] = base[base.length-1][j];

					}
					
				}
			}
			
			
			System.out.println("=================c[][]=================");
			for (int j = 0; j < c.length; j++) {
				for (int k = 0; k < c[j].length; k++) {
					System.out.print(c[j][k]+"   ");
				}
				System.out.println();
			}
			System.out.println("--------b");
			//如果c中存在两行是相同的，要额外处理

			for (int j = 0; j < b.length; j++) {
				System.out.println(b[j]);
			}
			
			System.out.println("end=================c[][]=================");
			
			int[] index_chongfu = choosejuzhenglei2(c);
			int choosejuzhenglei2 = index_chongfu[1];
			
			
			System.out.println("asasasasasasasasasa++++++"+choosejuzhenglei2);
			
			if (choosejuzhenglei2>0) {
				double[] duoyuanyici = hunhuanjiexiangliang(c, b,index_chongfu);
				asb[i][0] = 0;
				for (int j = 0; j < duoyuanyici.length; j++) {
					asb[i][j+1] = duoyuanyici[j];
				}
				
			}else {
				double[] duoyuanyici = MathUtils.duoyuanyici(c, b);
				asb[i][0] = 1;
				for (int j = 0; j < duoyuanyici.length; j++) {
					asb[i][j+1] = duoyuanyici[j];
				}
			}
			
			
			
			
			
			
			
			
			System.out.println(Arrays.toString(asb[i]) + "                               ........................"
					+ choosejuzhenglei +"============="+rejectjuzhenghang);
		}
//		double[][] st = new double[a.length][a.length];
//		for (int j = 0; j < st.length; j++) {
//			st[j][0] = 1;
//		}
//		for (int j = 0; j < asb.length; j++) {
//			for (int k = 0; k < asb[j].length; k++) {
//				st[j][k + 1] = asb[j][k];
//			}
//		}
		double[][] st = asb;
		double result[][] = new double[st.length][st.length];
		// 将特征向量结果单位化
		for (int j = 0; j < st.length; j++) {
			double sum = 0;
			for (int k = 0; k < st[j].length; k++) {
				sum += st[j][k] * st[j][k];
			}
			for (int k = 0; k < st[j].length; k++) {
//				result[j][k] = st[j][k] / Math.sqrt(sum);
				result[j][k] = st[j][k];
			}
		}

		return result;//我不知道为什么之前返回st，是我写错了吗，还是调试忘记改回来了
	}

	/**
	 * 	二元一次方程组的解，包括通解的情况
	 * @param base
	 * @param bb
	 * @return
	 */
	private static double[] erweifangchengzu_tongjie(double[][] base,double[] bb) {
		
		double[] result = new double[2];
		
		//上三角化
		if (base[1][0]!=0&&base[0][0]!=0) {
			base[1][1] = base[1][1] - base[0][1]*(base[1][0]/base[0][0]);
			base[1][0] = 0;
			bb[1] = bb[1] - bb[0]*(base[1][0]/base[0][0]);
		}
		

		
		
		
		{
			double[] ds0 = base[0];
			boolean isall0_0 = true;
			for (int j = 0; j < ds0.length; j++) {
				double d = ds0[j];
				if (Math.abs(d)>MathHUtils.jingdu) {
					isall0_0=false;
					break;
				}
			}
			if (isall0_0) {
				double[] ds1 = base[1];
				if (Math.abs(ds1[0])>MathHUtils.jingdu&&Math.abs(ds1[1])>MathHUtils.jingdu) {//如果第一个不等于0
					result[0] = 1;
					result[1] = (bb[1]-ds1[0])/ds1[1];
					
				}else if(Math.abs(ds1[0])>MathHUtils.jingdu&&Math.abs(ds1[1])<=MathHUtils.jingdu){
					
					result[0] = bb[0]/ds1[0];
					result[1]=1;

				}else if(Math.abs(ds1[0])<=MathHUtils.jingdu&&Math.abs(ds1[1])>MathHUtils.jingdu){
					
					
					result[0] = 1;
					result[1]= bb[1]/ds1[1];
					
				}else {

					result[0] = 1;
					result[1] = 1;
						
				}
				
				
			}
		}
		
		{
			double[] ds1 = base[1];
			boolean isall0_1 = true;
			for (int j = 0; j < ds1.length; j++) {
				double d = ds1[j];
				if (Math.abs(d)>MathHUtils.jingdu) {
					isall0_1=false;
					break;
				}
			}
		
			
			
			if (isall0_1) {
				double[] ds0 = base[0];
				if (Math.abs(ds0[0])>MathHUtils.jingdu&&Math.abs(ds0[1])>MathHUtils.jingdu) {//如果第一个不等于0
					result[0] = 1;
					result[1] = (bb[1]-ds0[0])/ds0[1];
					
				}else if(Math.abs(ds0[0])>MathHUtils.jingdu&&Math.abs(ds0[1])<=MathHUtils.jingdu){
					
					result[0] = bb[0]/ds0[0];
					result[1]=1;

				}else if(Math.abs(ds0[0])<=MathHUtils.jingdu&&Math.abs(ds0[1])>MathHUtils.jingdu){
					
					
					result[0] = 1;
					result[1]= bb[1]/ds0[1];
					
				}else {

					result[0] = 1;
					result[1] = 1;
						
				}
				
				
			}
			
			
			
			return result;
		
		}
	}

	/**
	 * 求解特征向量的时候，用代数余子项求解的时候，可能存在代数余子式的秩依然不满足，必须循环用代数余子式来求最终的一个解
	 * @param c
	 * @param b
	 * @return
	 * @throws Exception 
	 */
	private static double[] hunhuanjiexiangliang(double[][] a, double[] b,int[] index) throws Exception {
		// TODO Auto-generated method stub
		double[][] base = copy(a);

		if (base.length==2) {


//			double[] erweifangchengzu_tongjie = erweifangchengzu_tongjie(base,b);
//			return erweifangchengzu_tongjie;

			if (Math.abs(base[0][0])>MathHUtils.jingdu) {
				double[] result = new double[base.length];
				result[1] = -base[0][1]/base[0][0];
				result[0] = 1;
				return result ;
			}else if(Math.abs(base[0][1])>MathHUtils.jingdu){
				double[] result = new double[base.length];
				result[1] = 1;
				result[0] = 0;
				return result ;
			}else {
				double[] result = new double[base.length];
				result[1] = 1;
				result[0] = 1;
				return result ;

			}
			
			
			
		}
		
		
		
		double[][] c = new double[a.length - 1][a.length - 1];

		int choosejuzhenglei = choosejuzhenglei(base);
		int rejectjuzhenghang = index[1];
		
		
//		System.out.println("......................" + choosejuzhenghang);
		for (int k = 0; k < b.length; k++) {
//			System.out.println("万恶之源"+(-base[k + choosejuzhenghang][0]));
			if (rejectjuzhenghang==k) {
				continue;
			}
			
			b[k] = -base[k][choosejuzhenglei];
		}
		if (rejectjuzhenghang!=b.length) {
			for (int j = 0; j < c.length; j++) {
				b[b.length-1] = -base[base.length-1][choosejuzhenglei];
			}
		}
		
		
		
		for (int k = 0; k < c.length; k++) {
			if (rejectjuzhenghang==k) {
				continue;
			}
			for (int j = 0; j < c.length; j++) {
				if (choosejuzhenglei<=j) {
					c[k][j] = base[k][j + 1];

				}else {
					c[k][j] = base[k][j];
				}
				
			}
		}
		
		if (rejectjuzhenghang!=c.length) {
			for (int j = 0; j < c.length; j++) {
				if (choosejuzhenglei<=j) {
					c[c.length-1][j] = base[base.length-1][j + 1];
				}else {
					c[c.length-1][j] = base[base.length-1][j];

				}
				
			}
		}
		
		int[] index_chongfu = choosejuzhenglei2(c);
		
		int choosejuzhenglei2 = index_chongfu[1];
		
		double[] result = new double[base.length-1];
		
		if (choosejuzhenglei2>0) {
			double[] duoyuanyici = hunhuanjiexiangliang(c, b,index_chongfu);
			result[0] = 0;
			
			for (int j = 0; j < duoyuanyici.length; j++) {
				result[j+1] = duoyuanyici[j];
			}
			
		}else {
			double[] duoyuanyici = MathUtils.duoyuanyici(c, b);
			result[0] = 1;
			for (int j = 0; j < duoyuanyici.length; j++) {
				result[j+1] = duoyuanyici[j];
			}
		}
		
		
		
		
		return result;
	}
	
	
	

	/**
	 * 在求解特征向量的过程中，要剔除选项完全相同的，使用对矩阵秩大小的判断就可以求出结果了，但现在感觉秩也不好求
	 * 
	 * @param a
	 * @return 这个方法还不完全，但针对3维矩阵是完全够了，更高维次的需要更多判断，运气好也无需判断啦 这里就判断了相邻两行是否相同
	 * @throws Exception
	 */
	private static int choosejuzhenglei(double[][] a) throws Exception {
		
		for (int i = 0; i < a.length; i++) {
			boolean isallzero = true;
			for (int j = 0; j < a[i].length; j++) {
				if (Math.abs(a[i][j])<0.00001) {
					isallzero = false;
					break;
				}
			}
			if (isallzero) {
				return i;
			}
		}
		return 0;
	}

	
	
	/**
	 * 找出两行相同的，或者说一行巧合是另一行的倍数的，没找到返回-1，找到了返回第二行index
	 * @param a
	 * @return
	 * @throws Exception
	 */
	private static int[] choosejuzhenglei2(double[][] a) throws Exception {
		int i;
		int j;
		for (i = 0; i < a.length - 1; i++) {
			double[] ds = a[i];
			for ( j = i+1; j < a.length; j++) {
				double[] ds2 = a[j];
				boolean isbeishu = isbeishu(ds, ds2);
				System.out.println(isbeishu);
				if (isbeishu) {
					int[] result = {i,j};
					return result;
				}
			}
			j= 0;
		}

		

		
		int[] result = {-1,-1};
		return result;
	}
	
	/**
	 * 某一行和另一行是倍数关系
	 * @return
	 */
	private static boolean isbeishu(double[] ds1,double[] ds2) {
		
		double bei = 1;
		System.out.println(ds1[0]+"  "+ds1[1]);
		System.out.println(ds2[0]+"  "+ds2[1]);
		for (int i = 0; i < ds2.length; i++) {
			double asa = ds1[i]/ds2[i];
			if (i==0) {
				bei =asa;
				continue;
			}
			
			if (bei!=asa) {
				System.out.println(bei+"倍数"+asa);
				return false;
			}
			
		}
		
		
		return true;
	}
	
	
	
	
	
	
	
	/**
	 * 剔除不合适的行
	 * @param a
	 * @return
	 * @throws Exception
	 */
	private static int rejectjuzhenghang(double[][] a) throws Exception {
		
		for (int i = 0; i < a.length; i++) {
			boolean isallzero = true;
			for (int j = 0; j < a[i].length; j++) {
				if (a[i][j]!=0) {
					isallzero = false;
					break;
				}
			}
			if (isallzero) {
				return i;
			}
		}
		
		return a.length-1;
	}

	
	
	
	
	
	
	/**
	 * 矩阵的乘法
	 * 
	 * @param a
	 * @return
	 * @throws Exception
	 */
	public static double[][] chenfa(double[][] a, double[][] b) {

		return multiplyMatrices(a,b);
	}

	static double[][] multiplyMatrices(double[][] firstMatrix, double[][] secondMatrix) {
	    double[][] result = new double[firstMatrix.length][secondMatrix[0].length];

	    for (int row = 0; row < result.length; row++) {
	        for (int col = 0; col < result[row].length; col++) {
	            result[row][col] = multiplyMatricesCell(firstMatrix, secondMatrix, row, col);
	        }
	    }

	    return result;
	}
	static double multiplyMatricesCell(double[][] firstMatrix, double[][] secondMatrix, int row, int col) {
	    double cell = 0;
	    for (int i = 0; i < secondMatrix.length; i++) {
	        cell += firstMatrix[row][i] * secondMatrix[i][col];
	    }
	    return cell;
	}
	
	/**
	 * 	求矩阵的p次幂
	 * 为什么要这个呢？因为性能比直接成要好，直接乘是N而这个是logN
	 * @param m
	 * @param p
	 * @return
	 */
	public static double[][] matrixPower(double[][] m, int p) {
		// TODO Auto-generated method stub
		
		double[][] res = new double[m.length][m[0].length];
		for (int i = 0; i < res.length; i++) {
			res[i][i] = 1;
		}
		double[][] t = m;
		for (; p != 0 ; p>>=1) {
			
			if ((p&1)!=0) {
				res = chenfa(res, t);
			}
			t = chenfa(t, t);//这是无论如何都要乘的，这个代表位数
		}
		
		return res;
	}
	
	
	
	
	
	
	
	
	
	/**
	 * 矩阵的转置
	 * 
	 * @param a
	 * @return
	 */
	public static double[][] zhuanzhi(double[][] a) {
		double[][] asa = new double[a[0].length][a.length];

		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < a[i].length; j++) {
				asa[j][i] = a[i][j];
			}
		}

		return asa;
	}

	/**
	 * 矩阵的加法
	 * 
	 * @param a
	 * @param b
	 * @return
	 */
	public static double[][] jiafa(double[][] a, double[][] b) {
		double[][] asa = new double[a.length][a[0].length];
		if (a.length != b.length || a[0].length != b[0].length) {
			throw new RuntimeException("哥们你这个矩阵长度都有问题呀，矩阵之间的行列数要相同才能相加");
		}
		for (int i = 0; i < asa.length; i++) {
			for (int j = 0; j < asa[i].length; j++) {
				asa[i][j] = a[i][j] + b[i][j];
			}
		}

		return asa;
	}

	

	/**
	 * 单位矩阵
	 * @param length
	 * @return
	 */
	public static double[][] getI(int length) {
		// TODO Auto-generated method stub
		double[][] I = new double[length][length];
		
		for (int j = 0; j < I.length; j++) {
			I[j][j] = 1;
		}
		return I;
	}
	
	/**
	 * 初始化一个全0方正矩阵
	 * @param length
	 * @return
	 */
	public static double[][] get0(int length) {
		// TODO Auto-generated method stub
		double[][] ling = new double[length][];
		
		for (int j = 0; j < ling.length; j++) {
			ling[j] = new double[length];
		}
		return ling;
	}
	
	/**
	 * 初始化一个全d方正矩阵
	 * @param length
	 * @return
	 */
	public static double[][] getD(int length,double d) {
		// TODO Auto-generated method stub
		double[][] ling = new double[length][];
		
		for (int j = 0; j < ling.length; j++) {
			ling[j] = new double[length];
		}
		return ling;
	}
	
	
	public static double[][] getD(double[][] suanzi,double d) {
		// TODO Auto-generated method stub
		double[][] ling = new double[suanzi.length][suanzi[0].length];
		
		for (int i = 0; i < ling.length; i++) {
			for (int j = 0; j < ling[i].length; j++) {
				ling[i][j] = d;
			}
			

		}
		return ling;
	}
	
	
	
	
	/**
	 * 将一维数组变成二维的
	 * 会变成竖的
	 * @param length
	 * @return
	 */
	public static double[][] up2D(double[] a) {
		// TODO Auto-generated method stub
		double[][] ling = new double[a.length][1];
		
		for (int i = 0; i < ling.length; i++) {
			ling[i][0] = a[i];
		}
		
		
		return ling;
	}
	
	
	
	
	/**
	 * 	生成一个矩阵，除了指定位置，其他位置都是0的矩阵
	 * @param length
	 * @return
	 */
	public static double[][] get0_1(int length,int a,int b) {
		// TODO Auto-generated method stub
		double[][] get0 = get0(length);
		
		get0[a][b] = 1;
		
		return get0;
	}
	
	
	
	
	
	
	

	/**
	 * 乘法
	 * @param suanzi
	 * @param d
	 * @return
	 */
	public static double[][] chenfa(double[][] suanzi, double d) {
		// TODO Auto-generated method stub
		
		double[][] I = new double[suanzi.length][suanzi[0].length];

		for (int j = 0; j < I.length; j++) {
			for (int k = 0; k < I[j].length; k++) {
				I[j][k] = suanzi[j][k]*d;
			}
		}
		
		return I;
	}

	
	
	/**
	 * 打印一个矩阵
	 * @param a
	 */
	public static void print(double a[][]) {
		
		
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < a[i].length; j++) {
				
				System.out.print(a[i][j]+"   ");
			}
			System.out.println();
		}
		
		
	}
	public static void print(double a[]) {
		
		
		for (int i = 0; i < a.length; i++) {

				
				System.out.print(a[i]);
			
			System.out.println();
		}
		
		
	}
	
	
	/**
	 * 美化一下矩阵，就是把矩阵里面的值进行四舍五入
	 * @param a
	 * @param dianhou 保留的小数点数
	 */
	public static void beauty(double a[][],int dianhou) {
		
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < a[i].length; j++) {
				BigDecimal setScale = new BigDecimal(a[i][j]).setScale(dianhou, BigDecimal.ROUND_HALF_UP);
				a[i][j] = setScale.doubleValue();
			}
			
		}
		
		
	}
	
	public static void beauty(double a[],int dianhou) {
		
		for (int i = 0; i < a.length; i++) {
				BigDecimal setScale = new BigDecimal(a[i]).setScale(dianhou, BigDecimal.ROUND_HALF_UP);
				a[i]= setScale.doubleValue();
			
			
		}
		
		
	}
	
	
	
	public static double[][] copy(double a[][]) {
		double[][] result = new double[a.length][];
		
		for (int i = 0; i < a.length; i++) {
			result[i] = new double[a[i].length];
			for (int j = 0; j < a[i].length; j++) {
				result[i][j] = a[i][j];
			}
		}
		return result;
		
		
	}
	
	
	public static double[][] copy1(double a[][]) {
		double[][] result = new double[a.length][];
		
		for (int i = 0; i < a.length; i++) {
			result[i] = new double[a[i].length];
			for (int j = 0; j < a[i].length; j++) {
				result[i][j] = 1;
			}
		}
		return result;
		
		
	}
	
	
	public static double[][] reverse_hang(double a[][]) {
		double[][] copy = copy(a);
		
		double[][] result = new double[copy.length][];
		
		for (int i = 0; i < result.length; i++) {
			result[i] = copy[copy.length-1-i];
		}
		return result;
		
		
	}
	
	
	/**
	 * 	矩阵的拼接，行
	 * @return
	 */
	public static double[][] add_hang(double[][] a,double[][] b,int asa){
		
		double[][] result = new double[a.length+b.length][];
		double[][] copy_a = copy(a);
		double[][] copy_b = copy(b);
		
		for (int i = 0; i < result.length; i++) {
			
			if (i<asa) {
				result[i] = copy_a[i];
				
			}else if(i>=asa&&i<(asa+copy_b.length)) {
				result[i] = copy_b[i-asa];
				
			}else {
				result[i] = copy_a[i-copy_b.length];
				
			}
					
			
			
		}
		
		
		
		
		return result;
	}
	
	/**
	 * 	矩阵的拼接，列
	 * @return
	 */
	public static double[][] add_lie(double[][] a,double[][] b,int asa){
		
		double[][] result = new double[a.length][a[0].length+b[0].length];
		double[][] copy_a = copy(a);
		double[][] copy_b = copy(b);
		
		for (int i = 0; i < result.length; i++) {
					
			for (int j = 0; j < result[i].length; j++) {
				int index_j = j;
				if (index_j<asa) {
					result[i][j] = copy_a[i][index_j];

				}else if(index_j>=asa&&index_j<(asa+copy_b[i].length)) {
					index_j = index_j-asa;
					
					result[i][j] = copy_b[i][index_j];
				}else {
					
					index_j = index_j-copy_b[i].length;
					
					result[i][j] = copy_a[i][index_j];
				}
				
				
				
			}
			
		}
		
		
		
		
		
		return result;
	}
	
	
	
	
	
	/**
	 * 判断nXm矩阵（n>=m）的秩是否是m
	 * @return
	 */
	public static boolean ismangzhi(double[][] jisuan) {
		
		//一个思路是result是否是满秩的不好判断是因为它是mXn的矩阵，那么如果我把它切成一个mXm的矩阵
				double[][] jisuan2 = null;

				for (int i = 0; i < jisuan.length; i++) {
					double[] ds = jisuan[i];
					
					if (isall0(ds)) {
						continue;
					}
					
					
					if (jisuan2==null) {
						jisuan2 = new double[1][];
						jisuan2[0] = ds;
						
					}else {
						double[][] add = new double[1][];
						add[0] = ds;
						
						jisuan2 = MathHUtils.add_hang(jisuan2, add, jisuan2.length);
					}
					
					
					
				}
				
				boolean isall0 = true;
				
				if (jisuan2==null||jisuan2.length<1||jisuan2==null) {
//					System.out.println("不能");
					return false;

				}else if (jisuan2.length<jisuan2[0].length||jisuan2[0].length==0) {
//					System.out.println("不能");
					return false;

				}else {
					
					//排列组合，组成成各种mXm的方块矩阵
					
					
					List<int[]> zuhe_list = Calculate.zuhe_list(jisuan2.length, jisuan2[0].length);
					for (int i = 0; i < zuhe_list.size(); i++) {
						int[] js = zuhe_list.get(i);
						double[][] asa = new double[jisuan2.length][jisuan2.length];
						for (int j = 0; j < js.length; j++) {
							asa[j] = jisuan2[j];
							
						}
						double value_one = 0;
						try {
							value_one = Ni.hangleishivalue(asa);

						} catch (Exception e) {
							// TODO: handle exception
							return false;
						}
						
						if (Math.abs(value_one) > MathHUtils.to0) {
							isall0 = false;
							break;
						}
						
						
					}
					
					
					
					
				}
		
		
		
		return !isall0;
		
	}
	
	
	
	
	
	/**
	 * 判断是否满秩的方法二 
	 * @param jisuan
	 * @return
	 */
	public static boolean ismangzhi2(double[][] jisuan) {
		double hangleishivalue = 0;
		double[][] zhuanzhi = MathHUtils.zhuanzhi(jisuan);
		if (jisuan.length>jisuan[0].length) {//如果要判断的不是一个行列长度相同的矩阵，需要处理一下，用处理之后的矩阵判断
			double[][] chenfa = MathHUtils.chenfa(jisuan, zhuanzhi);
			hangleishivalue = Ni.hangleishivalue(chenfa);
			
		}else if(jisuan.length<jisuan[0].length){
			double[][] chenfa = MathHUtils.chenfa(zhuanzhi, jisuan);
			hangleishivalue = Ni.hangleishivalue(chenfa);

		}else {
			 hangleishivalue = Ni.hangleishivalue(jisuan);
		}
		
		
		
		if (Math.abs(hangleishivalue)<to0) {
			return false;
		}
		
		return true;
	}

	
	
	
	
	
	         
	
	
	
	
	
	
	
	private static boolean isall0(double[] asa) {
		
		
		boolean result = true;
		
		
		for (int i = 0; i < asa.length; i++) {
			if (Math.abs(asa[i])>=MathHUtils.to0) {
//			if (Math.abs(asa[i])==0) {
				result = false;
				break;
			}
		}
		
		
		return result;
		
	}
	
	
	/**
	 * 获取一个矩阵的子矩阵
	 * @param a
	 * @param p
	 * @param q
	 * @param r
	 * @param s
	 * @return
	 */
	public static double[][] zi(double[][] a,int p,int q,int r,int s){
		
		double[][] result = new double[q-p+1][s-r+1];
		
		for (int i = p; i < q; i++) {
			for (int j = r; j < s; j++) {
				result[i-p][j-r] = a[i][j];
			}
		}
		
		return result;
	}
	
	
	/**
	 * Hadamard积
	 * @param aa
	 * @param bb
	 * @return
	 */
	public static double[][] hadamard(double[][] aa,double[][] bb) {
		double[][] result = new double[aa.length][aa[0].length];
		for (int i = 0; i < aa.length; i++) {
			for (int j = 0; j < aa[i].length; j++) {
				result[i][j] = aa[i][j]*bb[i][j];
			}
		}
		
		return result;
	}
	
	
	
	/**
	 * Kronecker积
	 * @param aa
	 * @param bb
	 * @return
	 */
	public static double[][] Kronecker(double[][] aa,double[][] bb) {
		List<List<double[][]>> result = new ArrayList<>();
		for (int i = 0; i < aa.length; i++) {
			List<double[][]> e = new ArrayList<double[][]>(aa[i].length);
			result.add(e);
		}
		
		
		
		for (int i = 0; i < aa.length; i++) {
			for (int j = 0; j < aa[i].length; j++) {
				result.get(i).set(j, chenfa(bb, aa[i][j]));
			}
			
		}
		double [][] resultend = new double[aa.length*bb.length][aa[0].length*bb[0].length];
		
		for (int i = 0; i < result.size(); i++) {
			for (int j = 0; j < result.get(i).size(); j++) {
				double[][] ds = result.get(i).get(j);
				for (int k = 0; k < ds.length; k++) {
					for (int l = 0; l < ds.length; l++) {
						
						resultend[i*k][j*l] = ds[i][j];
						
					}
				}
				
				
			}
			
		}

		
		return resultend;
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	public static void main(String[] args) {

		// double[][] abc = {{2,1,1},{4,3,1}};
		// double[][] cba = {{1,2},{1,0},{1,1}};
		//
		// double[][] chenfa = chenfa(cba, abc);
		//
		// for (int i = 0; i < chenfa.length; i++) {
		// for (int j = 0; j < chenfa[i].length; j++) {
		// System.out.print(chenfa[i][j]+" ");
		// }
		// //System.out.println();
		// }

		// double[][] zhuanzhi = zhuanzhi(abc);
		//
		// for (int i = 0; i < zhuanzhi.length; i++) {
		// for (int j = 0; j < zhuanzhi.length; j++) {
		// System.out.print(zhuanzhi[i][j]+" ");
		// }
		// //System.out.println();
		// }
		
		
		
//		double[][] a = { { 0.67, -.41 }, { 0.74, -0.49 }, { 0.80, -0.57 }, { 0.57, 0.75 }, { 0.55, 0.66 },
//				{ 0.51, 0.60 } };
//
//		double sin = Math.sin(36 * Math.PI / 180);
//		double cos = Math.cos(36 * Math.PI / 180);
//		//System.out.println("sin1    " + sin);
//		//System.out.println("cos1    " + cos);
//		//System.out.println("输出的特别的看看吧");
//		double sum = 0;
//		int n = 0;
//		for (int i = 0; i < a.length; i++) {
//			double x = a[i][0] / a[i][1];
//			//System.out.println(x);
//			if (x < 1 && x > 0) {
//				sum += x;
//				n++;
//			}
//		}
//		double asin = Math.asin(sum / n);
//		asin = 90 - asin * 180 / Math.PI;
//		sin = Math.sin(asin * Math.PI / 180);
//		cos = Math.cos(asin * Math.PI / 180);
//		//System.out.println(asin + "...........");
//		//System.out.println("===================");
//		//System.out.println("再输出的特别的看看吧");
//		for (int i = 0; i < a.length; i++) {
//			//System.out.println(a[i][1] / a[i][0]);
//		}
//		//System.out.println("===================");
//
//		//System.out.println("sin    " + sin);
//		//System.out.println("cos    " + cos);
//		double[][] b = { { cos, sin }, { -sin, cos } };
//		double[][] chenfa = chenfa(a, b);
//		for (int i = 0; i < chenfa.length; i++) {
//			for (int j = 0; j < chenfa[i].length; j++) {
//				System.out.print(chenfa[i][j] + "   ");
//			}
//			//System.out.println();
//		}
//
		
		
		double[][] asA = getI(5);
		
		
		zi(asA, 0, 4, 0, 4);
		
		
	}
	
	
	
}
